package pl.put.to.regression;

import java.util.ArrayList;
import java.util.List;

import pl.put.to.regression.data.DataInstance;
import pl.put.to.regression.data.DataSet;
import Jama.Matrix;

public class LeastSquaresProblem {
	private DataSet data;
	private List<Double> coefficients;

	public LeastSquaresProblem(DataSet data) {
		this.data = data;
	}

	public void solve() {
		Matrix xiMatrix = new Matrix(data.getNumberOfVariables(), data.getNumberOfVariables());
		Matrix yixiVector = new Matrix(1, data.getNumberOfVariables());

		for (DataInstance instance : data.getInstances()) {
			double[][] xi = new double[1][data.getNumberOfVariables()];
			double[][] yixi = new double[1][data.getNumberOfVariables()];

			for (int i = 0; i < data.getNumberOfVariables(); ++i) {
				xi[0][i] = instance.getVariableValues().get(i);
				yixi[0][i] = instance.getClassVariableValue() * xi[0][i];
			}

			Matrix xiVectorHorizontal = new Matrix(xi);
			Matrix xiVectorVertical = xiVectorHorizontal.transpose();

			Matrix yixiVectorPart = new Matrix(yixi);

			yixiVector = yixiVector.plus(yixiVectorPart);
			xiMatrix = xiMatrix.plus(xiVectorVertical.times(xiVectorHorizontal));
		}

		Matrix result = xiMatrix.inverse().times(yixiVector.transpose());
		result = result.transpose();

		prepareResult(result);
	}

	private void prepareResult(Matrix result) {
		coefficients = new ArrayList<Double>();

		for (int i = 0; i < result.getColumnDimension(); ++i) {
			coefficients.add(result.get(0, i));
		}
	}

	public List<Double> getCoefficients() {
		return coefficients;
	}

}
